#if !defined(__RETOUR_VERS_LE_FUTUR_H)
#define __RETOUR_VERS_LE_FUTUR_H

#include "weather_report.h"

/**
 * Doc Emmett Brown, comme tout bon savant fou qui se respecte, sait
 * faire des changements de référentiel, et c'est précisément ce qui
 * nous intéresse. Vu qu'il maîtrise le temps, c'est lui qui sera de
 * bon conseil dans ces nombreuses situations où les Marty McFly ont
 * besoin de réponses (attention, ce ne sont pas des mauviettes).
 */
struct doc_emmett_brown {
	typedef temps::type_temps type_temps;
private:
	// Pour tout temps t, delta = t_du_referentiel_local - t_du_referentiel_distant
	type_temps delta_entre_les_deux_univers_;
	
	static doc_emmett_brown *instance_;
	
	doc_emmett_brown() throw() : delta_entre_les_deux_univers_(0) {}
	~doc_emmett_brown() throw() {}
public:
	static doc_emmett_brown &instance() {
		if(!instance_)
			instance_ = new doc_emmett_brown;
		return *instance_;
	}
	
	void set_delta(type_temps d) { delta_entre_les_deux_univers_ = d; }
	
	// Renvoie le temps t dans le référentiel local
	type_temps delta(type_temps t_du_referentiel_distant) { 
		return t_du_referentiel_distant + delta_entre_les_deux_univers_;
	}
	
	// Dit dans combien de temps se produira un moment donné en référentiel distant
	type_temps temps_restant_pour_que_se_produise(type_temps t_du_referentiel_distant) {
		return delta(t_du_referentiel_distant) - temps::maintenant();
	}
	
	// Dit de combien de temps le moment donné en référentiel distant est dépassé
	type_temps temps_depuis(type_temps t_du_referentiel_distant) {
		return -temps_restant_pour_que_se_produise(t_du_referentiel_distant);
	}
	
	// Dit si le facteur est déjà passé
	bool est_deja_passe(type_temps t_du_referentiel_distant) {
		return temps_restant_pour_que_se_produise(t_du_referentiel_distant) < 0;
	}
	
	// Dit si le facteur est en train de passer avec une marge d'erreur réglable
	bool est_en_train_de_se_produire(type_temps t_du_referentiel_distant, type_temps epsilon) {
		type_temps t = temps_restant_pour_que_se_produise(t_du_referentiel_distant);
		return t < epsilon && t > -epsilon;
	}
};

#endif
